package com.zby.test.util.reflect;

import com.zby.test.constant.StandardBasicTypes;
import com.zby.test.util.common.CommonUtil;
import com.zby.test.util.exception.GenericException;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created By zby on 17:42 2019/1/23
 * 获取对象集合
 */

public class PersistentObject<T> {

    /**
     * 类字面常量，这样比较安全，也比较方便
     */
    private Class<T> persistenceClass;


    private ResultSet resultSet;

    public PersistentObject() {
    }

    public PersistentObject(Class<T> persistenceClass) {
        this.persistenceClass = persistenceClass;
    }

    public PersistentObject(ResultSet resultSet) {
        this.resultSet = resultSet;
    }

    public PersistentObject(Class<T> persistenceClass, ResultSet resultSet) {
        this.persistenceClass = persistenceClass;
        this.resultSet = resultSet;
    }

    /**
     * Created By zby on 17:46 2019/1/23
     * 获取属性名称
     */
    public List<T> getPersist() {
        if (CommonUtil.isNull(persistenceClass))
            throw new GenericException("找不到这个类clazz = " + persistenceClass.getName());
        if (CommonUtil.isNull(resultSet))
            throw new GenericException("结果集为result = " + resultSet);
        List<T> list = new ArrayList<>();
        try {
            while (resultSet.next()) {
                Field[] fields = persistenceClass.getDeclaredFields();
                T obj = persistenceClass.newInstance();
                for (Field field : fields) {
                    String fieldName = field.getName();
                    String columnName = fieldName;
                    Matcher matcher = Pattern.compile("[A-Z]").matcher(columnName);
                    Type paramType = field.getGenericType();
                    if (StandardBasicTypes.BOOLEAN.equalsIgnoreCase(paramType.toString())) {
                        //设置修改修改的权限，对于bool类型的数据，我们只能修改器属性
                        field.setAccessible(true);
                        field.setBoolean(obj, resultSet.getBoolean("is_" + columnName));
                        break;
                    }
                    //通过字段名来获取字段值
                    while (matcher.find()) {
                        columnName = columnName.replace(matcher.group(), "_" + matcher.group().toLowerCase());
                    }
                    transformType(persistenceClass, resultSet, obj, fieldName, columnName, paramType);
                }
                list.add(obj);
            }
            return list;
        } catch (InstantiationException e) {
            System.out.println("实例化异常persistenceClass=" + persistenceClass);
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            System.out.println("非法访问异常persistenceClass=" + persistenceClass);
            e.printStackTrace();
        } catch (SQLException e) {
            System.out.println("结果集已经关闭resultSet=" + resultSet);
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 数据类型转换
     *
     * @param clazz
     * @param resultSet
     * @param obj
     * @param fieldName
     * @param columnName
     * @param paramType
     * @throws NoSuchMethodException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws SQLException
     */
    private void transformType(Class<T> clazz, ResultSet resultSet, T obj, String fieldName, String columnName, Type paramType) {
        Method method = null;
        String methodName = packMethodName(paramType, fieldName);
        try {
            if (StandardBasicTypes.LONG.equalsIgnoreCase(paramType.toString())) {
                method = clazz.getMethod(methodName, Long.class);
                method.setAccessible(true);
                method.invoke(obj, resultSet.getLong(columnName));
            } else if (StandardBasicTypes.STRING.equalsIgnoreCase(paramType.toString())) {
                method = clazz.getMethod(methodName, String.class);
                method.setAccessible(true);
                method.invoke(obj, resultSet.getString(columnName));
            } else if (StandardBasicTypes.INTEGER.equalsIgnoreCase(paramType.toString())) {
                method = clazz.getMethod(methodName, Integer.class);
                method.setAccessible(true);
                method.invoke(obj, resultSet.getInt(columnName));
            } else if (StandardBasicTypes.BIG_DECIMAL.equalsIgnoreCase(paramType.toString())) {
                method = clazz.getMethod(methodName, BigDecimal.class);
                method.setAccessible(true);
                method.invoke(obj, resultSet.getBigDecimal(columnName));
            } else if (StandardBasicTypes.DOUBLE.equalsIgnoreCase(paramType.toString())) {
                method = clazz.getMethod(methodName, Double.class);
                method.setAccessible(true);
                method.invoke(obj, resultSet.getDouble(columnName));
            } else if (StandardBasicTypes.FLOAT.equalsIgnoreCase(paramType.toString())) {
                method = clazz.getMethod(methodName, Float.class);
                method.setAccessible(true);
                method.invoke(obj, resultSet.getFloat(columnName));
            } else if (StandardBasicTypes.DATE.equalsIgnoreCase(paramType.toString())) {
                method = clazz.getMethod(methodName, Date.class);
                method.setAccessible(true);
                method.invoke(obj, (Date) resultSet.getTimestamp(columnName));
            } else {
                throw new GenericException("数据转型失败");
            }
        } catch (SQLException e) {
            System.out.println("结果集已经关闭resultSet=" + resultSet);
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            System.out.println("非法访问异常");
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            System.out.println("调用目标异常");
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            System.out.println("没有当前这个方法methodName=" + methodName);
        }
    }

    /**
     * Created By zby on 13:57 2019/1/24
     * 封装方法名称
     */
    private String packMethodName(Type paramType, String fieldName) {
        if (CommonUtil.isNull(fieldName))
            throw new GenericException("属性名称为空");
        if (CommonUtil.isNull(paramType))
            throw new GenericException("类型名称为空");
        return "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1, fieldName.length());
    }

}
